package com.lancoo.ccas52.config;

import com.alibaba.fastjson.JSON;
import com.lancoo.ccas52.pojo.response.basicPlatform.LoginUser_Ret;
import com.lancoo.ccas52.pojo.response.basicPlatform.UserInfo;
import com.lancoo.ccas52.service.YunBasicService;
import com.lancoo.ccas52.util.EnumResultCode;
import com.lancoo.ccas52.util.ResponseObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName AuthenticationFilter
 * @Description TODO
 * Authorization string 登录token值 //
 * userId        string    请求用户Id  //
 * userName    string    用户名  //
 * sysId        string    调用子系统ID //
 * <p>
 * ps: 若后台请求无法获取token值，则只传sysid,Authorization。 Authorization传:sysId的MD5并反转值且userId、userName 不传
 * @Author quin
 * @Date 2023/2/21 13:48
 */
@Component
@Slf4j
public class AuthenticationFilter implements HandlerInterceptor {

    @Resource
    private YunBasicService yunBasicService;
    @Autowired
    private RedissonClient redissonClient;


    /**
     * 覆盖父类的方法，
     * 如果返回true则可以调用方法，
     * 如果返回false则不调用
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }


        //请求带上令牌，Authorization:Bearer token
        String authorization = request.getHeader("Authorization");
        String sysId = request.getHeader("sysId");
        String userId = request.getHeader("userId");
        String userName = request.getHeader("userName");

//        //实现接口防刷
//        String key = "BrushResistance:" + request.getRequestURI() + ":" + authorization;
//        // 获取RRateLimiter实例
//        RRateLimiter limiter = redissonClient.getRateLimiter(key);
//        // 创建令牌桶数据模型，单位时间内产生多少令牌
//        limiter.trySetRate(RateType.OVERALL, 5, 1, RateIntervalUnit.SECONDS);
//        // 尝试访问数据，timeout 时间内，允许获得的数量permits(如果获取失败，返回false)
//        // 单位时间内不能获取到1个令牌，则返回，不阻塞
//        boolean tryAcquire = limiter.tryAcquire(1, 1, TimeUnit.SECONDS);
//        if (!tryAcquire) {
//            ResponseObject<Object> responseData = ResponseObject.ofFail("请求过于频繁，请稍后再试");
//            response.setContentType("text/html;charset=UTF-8");
//            response.getWriter().write(JSON.toJSONString(responseData));
//            return false;
//        }


        if (StringUtils.isNotBlank(authorization) && StringUtils.isNotBlank(sysId) && StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userName)) {
            //用户名 token验证
            UserInfo userInfoByToken = yunBasicService.getUserInfoByToken(authorization);

            if (userInfoByToken != null && userId != null && userName != null) {
                //前端访问时
                if (userInfoByToken.getUserID() == null || userInfoByToken.getUserName() == null) {
                    userInfoByToken.setUserID("");
                    userInfoByToken.setUserName("");
                }
                if (userInfoByToken.getUserID().equalsIgnoreCase(userId) && userInfoByToken.getUserName().equalsIgnoreCase(userName)){
                    return true;
                }
            }
        } else if (StringUtils.isNotBlank(authorization) && StringUtils.isNotBlank(sysId)) {
            //后台系统访问
            String Md5_AppId = DigestUtils.md5DigestAsHex(sysId.getBytes());
            StringBuffer sb = new StringBuffer(Md5_AppId);
            String strAccess_token = sb.reverse().toString();
            if (authorization.equals(strAccess_token)) {
                return true;
            }
        }

        ResponseObject<Object> responseData = ResponseObject.ofFail(EnumResultCode.INVALID_TOKEN);
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write(JSON.toJSONString(responseData));
        return false;
    }

}
